package com.xiaochong.tir.apiservice.scheduled;

import akka.dispatch.OnFailure;
import akka.dispatch.OnSuccess;
import com.alibaba.fastjson.JSON;
import com.xc.logclient.utils.LogTrace;
import com.xiaochong.service.common.config.redis.RedisServer;
import com.xiaochong.tir.apiservice.component.CmcDataCalculateComponent;
import com.xiaochong.tir.apiservice.component.CmcDataCountCalculateComponent;
import com.xiaochong.tir.apiservice.component.CoinMarketCapDataComponent;
import com.xiaochong.tir.apiservice.component.hbase.CurrencyInfoHbaseComponent;
import com.xiaochong.tir.apiservice.config.ExecutorConfig;
import com.xiaochong.tir.apiservice.service.ConceptCategoryService;
import com.xiaochong.tir.apiservice.service.CurrencyIndustryCategoryService;
import com.xiaochong.tir.apiservice.util.ApiLogTypeUtil;
import com.xiaochong.tir.common.data.hbasepo.*;
import com.xiaochong.tir.common.data.po.BasePeriodHistory;
import com.xiaochong.tir.common.data.po.ConceptCategory;
import com.xiaochong.tir.common.data.po.CurrencyIndustryCategory;
import com.xiaochong.tir.common.data.vo.app.MarketIndexVo;
import com.xiaochong.tir.common.exception.ErrorDataException;
import com.xiaochong.tir.common.util.*;
import com.xiaochong.tir.common.util.Process;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;


/**
 * Created by wujiaxing on 2018/4/24.
 * 获取CoinMarketCap数据定时任务
 */
@Component
public class CoinMarketCapScheduled {

    @Resource
    private CoinMarketCapDataComponent coinMarketCapDataComponent;

    @Resource
    private CmcDataCalculateComponent cmcDataCalculateComponent;

    @Resource
    private CmcDataCountCalculateComponent cmcDataCountCalculateComponent;

    @Resource
    private CurrencyInfoHbaseComponent currencyInfoHbaseComponent;

    @Resource
    private CurrencyIndustryCategoryService currencyIndustryCategoryService;

    @Autowired
    RedisServer redisServer;

    @Autowired
    private ConceptCategoryService conceptCategoryService;

    private void akkaProcess(String serviceName, Object o){
        try{
            Process process = AkkaRouterUtils.getProcess(serviceName);
            process.process(o, new OnSuccess() {
                @Override
                public void onSuccess(Object o) {
                    System.out.println("akka执行成功!");
                    LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE, LogTraceKeysUtils.DATA,"akka执行成功");
                }
            }, new OnFailure() {
                @Override
                public void onFailure(Throwable throwable) {
                    Exception e = new Exception(throwable);
                    e.printStackTrace();
                    LogTrace.error(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE
                            , e, ApiLogTypeUtil.API_ERROR);
                }
            },1200);
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error(e.getMessage(), e);
        }

    }

    @Async(ExecutorConfig.SCHEDULER_EXECUTOR_POOL)
    @Scheduled(cron="0 0/5 * * * ?")
    public void getCmcData() {
        LogTrace.beginTrace("每日定时任务getCmcData");
        LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE, LogTraceKeysUtils.DATA,"开始执行getCmcData定时任务");
        try {
            //获取CMS币种数据信息
            List<CmcCurrencyInfo> cmcCurrencyInfos = coinMarketCapDataComponent.ticker("CNY");
            LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE, LogTraceKeysUtils.DATA,"ticker完成");
            if(cmcCurrencyInfos==null || cmcCurrencyInfos.size()==0){
                throw new ErrorDataException("获取cmc货币数据失败！");
            }
            Map<String, CmcCurrencyInfo> cmcMap = cmcDataCalculateComponent.cmcCurrencyInfoListToMap(cmcCurrencyInfos);
            if(CollectionUtil.isBlank(cmcMap)){
                throw new ErrorDataException("获取cmc货币数据失败！");
            }

            CmcCurrencyGlobalInfo cmcCurrencyGlobalInfo = coinMarketCapDataComponent.global("CNY");
            LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE, LogTraceKeysUtils.DATA,"global完成");
            if(cmcCurrencyGlobalInfo==null){
                cmcCurrencyGlobalInfo = coinMarketCapDataComponent.getLastGlobal();
                if(cmcCurrencyGlobalInfo==null){
                    throw new ErrorDataException("获取cmc全球数据失败！");
                }
            }
            //插入redis中，微信机器人调用，最新全球市值、交易量
            if(StringUtils.isNotBlank(cmcCurrencyGlobalInfo.getTotal24hVolumeCny())){
                redisServer.set(RedisKeysUtils.CMC_GLOBAL_LAST_DATA, JSON.toJSONString(cmcCurrencyGlobalInfo));
            }

            caluMarketDataForApp(cmcMap ,cmcCurrencyGlobalInfo );

            List<DailyComprehensiveAnalysisInfo> dailyComprehensiveAnalysisInfos
                    = coinMarketCapDataComponent.saveDailyCurrencyInfor(cmcCurrencyInfos);
            LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE, LogTraceKeysUtils.DATA,"saveDailyCurrencyInfor完成");
            if(dailyComprehensiveAnalysisInfos==null || dailyComprehensiveAnalysisInfos.size()==0){
                throw new ErrorDataException("DailyComprehensiveAnalysisInfo解析失败！");
            }

            Map<String, DailyComprehensiveAnalysisInfo> dailyInfoMap = cmcDataCalculateComponent.dailyInfoListToMap(dailyComprehensiveAnalysisInfos);

            if(LocalDateTime.now().getHour()>=8 /*2*/&& !coinMarketCapDataComponent.confirmTodayCurrencies()){
                LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE, LogTraceKeysUtils.DATA, "开始执行currencies定时任务");
                Map<String, List<CurrencyHistorical>> currencies = coinMarketCapDataComponent.currencies();
                LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE, LogTraceKeysUtils.DATA, "货币历史数据爬取完成");
                //LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE,currencies);
            }


            Map<String,Object> akkaCurrencyGlobalMap = new HashMap<>();
            akkaCurrencyGlobalMap.put(AkkaParamUtils.CMC_CURRENCY_INFO_LIST,cmcCurrencyInfos);
            akkaCurrencyGlobalMap.put(AkkaParamUtils.CMC_GLOBAL_INFO,cmcCurrencyGlobalInfo);
            akkaCurrencyGlobalMap.put(AkkaParamUtils.CMC_CURRENCY_INFO_MAP,cmcMap);
            this.akkaProcess(AkkaParamUtils.AKKA_DIAGNOSIS_MARKET_PERFORMANCE_INDEX,akkaCurrencyGlobalMap);

            this.akkaProcess(AkkaParamUtils.AKKA_MORE_THAN_PERCENTAGE_SIX,cmcMap);
            this.akkaProcess(AkkaParamUtils.AKKA_DIAGNOSIS_AVERAGE_COST,cmcMap);
            this.akkaProcess(AkkaParamUtils.AKKA_CONCEPT_INDEX,cmcMap);
            this.akkaProcess(AkkaParamUtils.AKKA_COIN_RANK,cmcCurrencyInfos);


            this.akkaProcess(AkkaParamUtils.AKKA_DIAGNOSIS_PRESSURE_SUPPORTE,cmcMap);
            this.akkaProcess(AkkaParamUtils.AKKA_LONG_SHORT_TREND,cmcMap);



            Map<String,Object> akkaComprehensiveAnalysisMap = new HashMap<>();
            akkaComprehensiveAnalysisMap.put(AkkaParamUtils.CMC_CURRENCY_INFO_LIST,cmcCurrencyInfos);
            akkaComprehensiveAnalysisMap.put(AkkaParamUtils.CMC_CURRENCY_INFO_MAP,cmcMap);
            akkaComprehensiveAnalysisMap.put(AkkaParamUtils.DAILY_COMPREHENSIVE_ANALYSIS_INFO_LIST,dailyComprehensiveAnalysisInfos);
            akkaComprehensiveAnalysisMap.put(AkkaParamUtils.DAILY_COMPREHENSIVE_ANALYSIS_INFO_MAP,dailyInfoMap);
            this.akkaProcess(AkkaParamUtils.AKKA_COMPREHENSIVE_ANALYSIS,akkaComprehensiveAnalysisMap);


            Map<String,Object> akkaDiagnosisScoreMap = new HashMap<>();
            akkaDiagnosisScoreMap.put(AkkaParamUtils.CMC_CURRENCY_INFO_LIST,cmcCurrencyInfos);
            akkaDiagnosisScoreMap.put(AkkaParamUtils.CMC_CURRENCY_INFO_MAP,cmcMap);
            akkaDiagnosisScoreMap.put(AkkaParamUtils.DAILY_COMPREHENSIVE_ANALYSIS_INFO_LIST,dailyComprehensiveAnalysisInfos);
            akkaDiagnosisScoreMap.put(AkkaParamUtils.DAILY_COMPREHENSIVE_ANALYSIS_INFO_MAP,dailyInfoMap);
            akkaDiagnosisScoreMap.put(AkkaParamUtils.CMC_GLOBAL_INFO,cmcCurrencyGlobalInfo);
            this.akkaProcess(AkkaParamUtils.AKKA_DIAGNOSIS_SCORE,akkaDiagnosisScoreMap);


        } catch (ErrorDataException | IOException e) {
            e.printStackTrace();
            LogTrace.error("CoinMarketCapApiScheduled", e, ApiLogTypeUtil.API_ERROR);
        }

        BigDecimal weightMarketCap = cmcDataCalculateComponent.weightMarketCap();
        if(weightMarketCap!=null){
            LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE, LogTraceKeysUtils.DATA, "每日权重流通市值计算完成");
        }

        List<SumIndustrySupplyPrice> sumIndustrySupplyPrices = cmcDataCalculateComponent.sumIndustrySupplyPrice();
        if(sumIndustrySupplyPrices!=null && sumIndustrySupplyPrices.size()>0){
            LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE, LogTraceKeysUtils.DATA, "行业流通市值计算完成");
        }


        LogTrace.info(LogTraceKeysUtils.COIN_MARKET_CAP_API_SCHEDULED_TITLE, LogTraceKeysUtils.DATA, "coinMarketCapDataComponent.getCmcData定时执行完成");
        LogTrace.endTrace();
    }


    @Async(ExecutorConfig.SCHEDULER_EXECUTOR_POOL)
    @Scheduled(cron="0 0 0/12 * * ?")
//    @Scheduled(cron="0 30 0/1 * * ?")
    public void basePeriodHistory() {

        try {
            LogTrace.beginTrace("basePeriodHistory");

            //权重基期计算
            cmcDataCalculateComponent.calculateBasePeriodWeightIndexNew();

            //行业基期计算
            CurrencyIndustryCategory searchCurrencyIndustryCategory = new CurrencyIndustryCategory();
            searchCurrencyIndustryCategory.setParentId(0);
            searchCurrencyIndustryCategory.setEnableFlag( true );
            searchCurrencyIndustryCategory.setDeleteFlag( false );
            List<CurrencyIndustryCategory> parentIndustryCategories = currencyIndustryCategoryService.selectByEntityList(searchCurrencyIndustryCategory);
            for (CurrencyIndustryCategory parentIndustryCategory:parentIndustryCategories) {
                cmcDataCalculateComponent.calculateBasePeriodindustryNew(parentIndustryCategory);
            }

            //概念基期计算
            ConceptCategory conceptCategory=new ConceptCategory();
            conceptCategory.setDeleteFlag( false );
            conceptCategory.setEnableFlag( true );
            List<ConceptCategory> conceptCategoryList = conceptCategoryService.selectByEntityList( conceptCategory );
            for (ConceptCategory conceptCategory1: conceptCategoryList){
                cmcDataCalculateComponent.calculateBasePeriodConceptNew( conceptCategory1 );
            }
            LogTrace.info("basePeriodHistory" , "basePeriodHistory结束" , System.currentTimeMillis()+"");
                    LogTrace.endTrace();
        } catch (ErrorDataException e) {
            e.printStackTrace();
            LogTrace.error("CoinMarketCapApiScheduled", e, ApiLogTypeUtil.API_ERROR);
        }


    }

    /**
     * 计算APP端大盘数据
     * @param cmcMap
     * @param cmcCurrencyGlobalInfo
     */
    private void caluMarketDataForApp(Map<String, CmcCurrencyInfo> cmcMap ,CmcCurrencyGlobalInfo cmcCurrencyGlobalInfo){
        try {
            LogTrace.info("caluMarketDataForApp" , "计算APP大盘头部数据"  , new Date().toString());
            MarketIndexVo marketIndexVo = new MarketIndexVo();
            //上涨  下跌数统计
            int upCount = 0, downCount = 0;
            for (Map.Entry<String, CmcCurrencyInfo> cmcCurrencyInfo : cmcMap.entrySet()) {
                if(cmcCurrencyInfo.getValue().getPercentChange24h() != null){
                    if(new BigDecimal(cmcCurrencyInfo.getValue().getPercentChange24h()).compareTo(BigDecimal.ZERO) >= 0){
                        upCount ++;
                    }else{
                        downCount++;
                    }
                }else{
                    downCount++;
                }
            }
            marketIndexVo.setUpCount(upCount);
            marketIndexVo.setDownCount(downCount);

            marketIndexVo.setTotalVolume24h(cmcCurrencyGlobalInfo.getTotal24hVolumeCny());
            marketIndexVo.setTotalMarketCap(cmcCurrencyGlobalInfo.getTotalMarketCapCny());
            String changeRate = "0";
            if(cmcCurrencyGlobalInfo.getTotal24hVolumeUsd() == null || cmcCurrencyGlobalInfo.getTotalMarketCapUsd() ==null){
                }else {
                //24小时换手率
                changeRate = new BigDecimal(cmcCurrencyGlobalInfo.getTotal24hVolumeUsd()).multiply(new BigDecimal(100)).divide(
                        new BigDecimal(cmcCurrencyGlobalInfo.getTotalMarketCapUsd()),2 , BigDecimal.ROUND_HALF_UP).toString();
            }

            marketIndexVo.setChangRate(changeRate);

            redisServer.set(RedisKeyApp.MARKET_DATA  ,marketIndexVo);
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("caluMarketDataForApp" ,e );
        }
    }
}
